/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fi.uba.algo3.tp3.modelo.actores;

import fi.uba.algo3.tp3.modelo.notificaciones.StateNotification;
import fi.uba.algo3.tp3.modelo.servicios.ServicioJuego;
import fi.uba.algo3.tp3.modelo.actores.exceptions.*;

/**
 *
 * @author ariel
 */
public abstract class Fantasma extends Personaje {

    private final static int PUNTOS_BASICOS = 1000;
    private EstadoFantasma estado;

    public Fantasma(ServicioJuego servicio, Integer distanciaDeColision) {
        super(servicio, distanciaDeColision);
        this.estado = new EstadoFantasma(this);
    }

    public void vivirComido(ServicioJuego servicio) {
        try {
            estado.intentarEnjaular(observer);
        } catch (NoSePuedeEnjaularException e) {
            vivirComido();
        }
    }

    public void vivirHuyendo(ServicioJuego servicio, Pacman pacman) {
        if (!hayColision(pacman)) {
            vivirHuyendo(servicio);
        } else {
            try {
                this.morir(servicio);
            } catch (PuntoDePoderInactivoException e) {
            }
        }
    }

    public void atacar(ServicioJuego servicio) {
        Pacman pacman = servicio.getPacman();
        if (!hayColision(pacman)) {
            vivirAtacando(servicio);
        } else {
            try {
                pacman.morir(servicio);
            } catch (PuntoDePoderActivoException e) {
            }
        }
    }

    public void morir(ServicioJuego servicio) throws PuntoDePoderInactivoException {
        if (servicio.isTiempoPoderOn()) {
            try {
                estado.intenterComido(observer);
                servicio.aumentarPuntosJugador(PUNTOS_BASICOS);
            } catch (NoSePuedeComidoException ex) {
                ex.printStackTrace();
            }
        } else {
            throw new PuntoDePoderInactivoException();
        }
    }

    public Boolean estoyEnPosicionInicial() {
        Integer relativoYFantasma = y;
        Integer relativoXFantasma = x;
        if (posicionInicialX.equals(relativoXFantasma) && posicionInicialY.equals(relativoYFantasma)) {
            return true;
        }
        return false;
    }

    @Override
    public void reestablecer(ServicioJuego servicio) {
        x = posicionInicialX;
        y = posicionInicialY;
        estado.reestablecer();
        observer.notificar(StateNotification.NORMAL);
    }

    public void vivirEnJaula() {
        this.cambiarSentidoAVerticalArriba();
        x += sentidoX;
        y += sentidoY;
    }

    public void hayQueAtacar() {
        try {
            estado.intentarAtacar(observer);
        } catch (NoSePuedeAtacarException ex) {
            ex.printStackTrace();
        }

    }

    public void hayQueHuir() {
        try {
            estado.intentarHuir(observer);
        } catch (NoSePuedeHuirException ex) {
            ex.printStackTrace();
        }
    }


    public void setEstado(EstadoFantasma.Estado estado) {
        this.estado.actualizarEstado(estado);
    }

    public EstadoFantasma.Estado getEstado() {
        return estado.getEstado();
    }

    protected abstract void vivirComido();

    protected abstract void vivirHuyendo(ServicioJuego servicio);

    protected abstract void vivirAtacando(ServicioJuego servicio);

    @Override
    protected void vivir(ServicioJuego servicio) {
        estado.manejarEstado(servicio);
    }

    protected Boolean hayColision(Personaje p) {
        int xDeP=p.getX()+p.getDistanciaDeColision();
        int yDeP=p.getY()+p.getDistanciaDeColision();
        int xFan = (int) Math.abs(xDeP - this.getX());
        int yFan = (int) Math.abs(yDeP - this.getY());
        int min = xFan < yFan ? xFan : yFan;
        int distancia=Math.abs(xFan + yFan - (min >> 1) - (min >> 2) + (min >> 4));
        if((((p.getDistanciaDeColision()+(this.distanciaDeColision))-distancia) > 0)) {
            return true;
        }
        return false;
//        if ((per.getX() < (this.getX() + (this.getDistanciaDeColision()))) && (this.getX() < per.getX() + (per.getDistanciaDeColision())) && (per.getY() < this.getY() + (this.getDistanciaDeColision()))) {
//            return this.getY() < per.getY() + (per.getDistanciaDeColision() * 2);
//        }
//        return false;

    }

}




